package com.ltkj.baseplatform.service.impl;

import cn.hutool.core.util.IdUtil;
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.ltkj.baseplatform.domain.WuserExt;
import com.ltkj.baseplatform.domain.bo.LoginBodyBo;
import com.ltkj.baseplatform.domain.vo.UserLoginVO;
import com.ltkj.baseplatform.feign.RemoteAuthService;
import com.ltkj.baseplatform.feign.RemoteSysemUserService;
import com.ltkj.baseplatform.mapper.WuserExtMapper;
import com.ltkj.baseplatform.service.IWXUserService;
import com.ltkj.baseplatform.util.EidUtil;
import com.ltkj.baseplatform.util.IdCardUtil;
import com.ltkj.common.core.constant.SecurityConstants;
import com.ltkj.common.core.constant.UserConstants;
import com.ltkj.common.core.domain.R;
import com.ltkj.common.core.utils.StringUtils;
import com.ltkj.common.core.utils.bean.BeanUtils;
import com.ltkj.common.core.web.domain.AjaxResult;
import com.ltkj.common.security.utils.SecurityUtils;
import com.ltkj.system.api.RemoteUserService;
import com.ltkj.system.api.domain.SysUser;
import com.ltkj.system.api.domain.WxUser;
import com.ltkj.system.api.model.LoginUser;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.HashMap;
import java.util.Objects;

@Service
@RefreshScope
public class WXUserServiceImpl implements IWXUserService {

    @Value("${wx.tDeptId}")
    private Long tDeptId;

    @Value("${wx.defaultPwd}")
    private String defaultPwd;

    @Value("${wx.roleId}")
    private Long roleId;

    @Value("${wx.code2SessionUrl}")
    private String code2SessionUrl;
    @Value("${wx.appid}")
    private String appid;
    @Value("${wx.secret}")
    private String secret;
    @Value("${wx.grant_type}")
    private String grantType;

    /**
     * 身份证验证相关
     */
    @Value("${tx.secretId}")
    private String secretId;
    @Value("${tx.secretKey}")
    private String secretKey;
    @Value("${tx.merchantId}")
    private String merchantId;
    @Value("${tx.motion.merchantId}")
    private String motionMerchantId;

    @Autowired
    private WuserExtMapper wuserExtMapper;

    @Autowired
    private RemoteSysemUserService remoteSysemUserService;

    @Autowired
    private RemoteAuthService remoteAuthService;

    @Autowired
    private RemoteUserService remoteUserService;

    @Override
    @Transactional(isolation = Isolation.READ_UNCOMMITTED)
    public R<?> wxLogin(String code) {
        R<?> r = R.ok();

        //调用小程序的登录接口,通过code获取openid
        String url = code2SessionUrl+"?appid="+appid+"&secret="+secret+"&js_code="+code+"&grant_type="+grantType;
        String resultJson = HttpUtil.get(url);
        System.out.println("resultJson="+resultJson);
        JSONObject jsO = JSONUtil.parseObj(resultJson);

        String openid = "";
        if(StringUtils.isNotEmpty(""+jsO.get("openid")) || (Integer)jsO.get("errcode") == 0) {
            openid = String.valueOf(jsO.get("openid"));
        } else {
            return R.fail(jsO.get("errmsg"));
        }

        if(StringUtils.isEmpty(openid) || "null".equals(openid)) {
            r = R.fail("openid不能为空!");
            return r;
        }
        //判断是否存在该openid,不存在则注册
        WuserExt wuserExt = wuserExtMapper.selectWuserExtByOpenid(openid);
        if(wuserExt == null) {
            //注册
            SysUser sysUser = new SysUser();
            sysUser.setDeptId(tDeptId);
            Long userId = IdUtil.getSnowflakeNextId();
            sysUser.setUserId(userId);
            sysUser.setUserName(String.valueOf(userId));
            sysUser.setNickName("用户"+String.valueOf(userId).substring(13,19));
            sysUser.setUserType("01");
            sysUser.setPassword(defaultPwd);
            sysUser.setStatus("0");
            sysUser.setDelFlag("0");
            sysUser.setCreateBy("system");
            sysUser.setCreateTime(new Date());
            sysUser.setRemark("系统自动创建");

            R<Boolean> rb = remoteSysemUserService.registerForWx(sysUser, roleId,SecurityConstants.INNER);
            if(rb.getData()){
                //注册成功
                LoginBodyBo loginBodyBo = new LoginBodyBo();
                loginBodyBo.setUsername(sysUser.getUserName());
                loginBodyBo.setPassword(defaultPwd);
                r = remoteAuthService.login(loginBodyBo);
                if(r.getCode() == 200){
                    //登录成功
                    String token = ((HashMap<String, Object>)r.getData()).get("access_token").toString();

                    //关联额外属性
                    wuserExt = new WuserExt();
                    wuserExt.setOpenid(openid);
                    wuserExt.setUserId(userId);
                    wuserExt.setPhoneAuth("1");
                    wuserExt.setIdcodeAuth("1");
                    wuserExtMapper.insertWuserExt(wuserExt);

                    wuserExt = wuserExtMapper.selectWuserExtByOpenid(openid);
                    UserLoginVO userLoginVO = new UserLoginVO();
                    userLoginVO.setAccessToken(token);
                    userLoginVO.setWuserExt(wuserExt);
                    r = R.ok(userLoginVO);
                }

            } else {
                return R.fail("新增用户失败");
            }

        } else {
            LoginBodyBo loginBodyBo = new LoginBodyBo();
            loginBodyBo.setUsername(wuserExt.getUserName());
            loginBodyBo.setPassword(wuserExt.getPassword());
            r = remoteAuthService.loginForWx(loginBodyBo);
            if(r.getCode() == 200){
                UserLoginVO userLoginVO = new UserLoginVO();
                userLoginVO.setAccessToken(((HashMap<String, Object>)r.getData()).get("access_token").toString());
                R<LoginUser> userR = remoteUserService.getUserInfo(wuserExt.getUserName(), SecurityConstants.INNER);
                wuserExt.setRoles(userR.getData().getSysUser().getRoles());
                userLoginVO.setWuserExt(wuserExt);
                r = R.ok(userLoginVO);
            }
        }
        return r;
    }

    @Override
    public AjaxResult checkIdCard(String idCard, String name) {
            IdCardUtil idCardUtil = new IdCardUtil();
            AjaxResult r = idCardUtil.IdCardVerification(idCard, name,secretId ,secretKey);
            if(r.isSuccess()) {
                Long userId = SecurityUtils.getLoginUser().getUserid();
                WuserExt wuserExt = wuserExtMapper.selectWuserExtByUserId(userId);
                wuserExt.setIdcodeAuth("0");
                wuserExt.setUserIdcode(idCard);
                wuserExt.setRealName(name);
                wuserExtMapper.updateWuserExt(wuserExt);
                return AjaxResult.success("认证成功");
            }
            return r;
    }

    /**
     * 微信端修改个人信息
     * @param user
     * @return
     */
    @Override
    public R<?> editUser(WuserExt user) {
        if (StringUtils.isNotEmpty(user.getUserIdcode()) && !checkIdCardUnique(user)) {
            return R.fail("当前身份证号码已存在！");
        }
        WuserExt wuserExt = wuserExtMapper.selectWuserExtByUserId(user.getUserId());
        if (!StringUtils.equals(wuserExt.getPhonenumber(), user.getPhonenumber())) {
            // 手机号已变更，认证状态改为“未认证”
            user.setPhoneAuth("1");
        }
        if (!StringUtils.equals(wuserExt.getUserIdcode(), user.getUserIdcode())) {
            // 身份证号已变更，身份认证、人脸认证状态改为“未认证”
            user.setIdcodeAuth("1");
            user.setFaceAuth("1");
        }
        // 更新扩展字段
        int i = wuserExtMapper.updateWuserExt(user);
        if (i < 1) {
            return R.fail();
        }
        return remoteSysemUserService.editUser(user, SecurityConstants.INNER);
    }

    /**
     * 微信退出登录
     */
    @Override
    public R<?> wxLogout() {
        return remoteAuthService.logout(SecurityConstants.INNER);
    }

    @Override
    public R<WxUser> getWxUserInfo(Long userId) {
        WuserExt wuserExt = wuserExtMapper.selectWuserExtByUserId(userId);
        if (wuserExt == null) {
            return R.fail("用户不存在");
        }
        WxUser wxUser = new WxUser();
        BeanUtils.copyBeanProp(wxUser, wuserExt);
        return R.ok(wxUser);
    }

    /**
     * 查询微信用户信息
     * @param userId
     * @return
     */
    @Override
    public R<WuserExt> getWxUserInfoV2(Long userId) {
        WuserExt wuserExt = wuserExtMapper.selectWuserExtByUserId(userId);
        if (wuserExt == null) {
            return R.fail("用户不存在");
        }
        return R.ok(wuserExt);
    }

    /**
     * 获取E证通token
     *  appKey
     *      motion 体育场（运动公园）
     *      island 生态岛
     * @param appKey 小程序应用别名 “生态岛”小程序默认为空，其余需传入对应的标识
     * @return
     */
    @Override
    public AjaxResult getEidToken(String appKey) {
        String currMerchantId = merchantId;
        if (StringUtils.equals("motion", appKey)) {
            currMerchantId = motionMerchantId;
        }
        Long userId = SecurityUtils.getLoginUser().getUserid();
        WuserExt wuserExt = wuserExtMapper.selectWuserExtByUserId(userId);
        if (!StringUtils.equals("0", wuserExt.getIdcodeAuth())) {
            return AjaxResult.error("请先进行身份认证。");
        }
        String userIdcode = wuserExt.getUserIdcode();
        String realName = wuserExt.getRealName();
        EidUtil eidUtil = new EidUtil();
        return eidUtil.getEidToken(userIdcode, realName, secretId, secretKey, currMerchantId);
    }

    @Override
    public AjaxResult getEidResult(String eidToken) {
        EidUtil eidUtil = new EidUtil();
        AjaxResult eidResult = eidUtil.getEidResult(secretId, secretKey, eidToken);
        checkEidResult(eidResult);
        return eidResult;
    }

    private void checkEidResult(AjaxResult eidResult) {
        // E证通接口未报错，继续判断返回报文
        if (eidResult.isSuccess()) {
            Object o = eidResult.get(AjaxResult.DATA_TAG);
            // 判断返回报文中errCode
            if (!Objects.isNull(o) && !StringUtils.equals(o.toString(), "null")) {
                JSONObject entries = JSONUtil.parseObj(o);
                Integer errCode = entries.getInt("ErrCode");
                // 判断认证成功后保存数据库
                if (null != errCode && errCode.equals(0)) {
                    Long userId = SecurityUtils.getLoginUser().getUserid();
                    WuserExt wuserExt = wuserExtMapper.selectWuserExtByUserId(userId);
                    wuserExt.setFaceAuth("0");
                    wuserExtMapper.updateWuserExt(wuserExt);
                }
            }
        }
    }

    /**
     * 校验身份证号码是否唯一
     * @param wuserExt
     * @return
     */
    @Override
    public boolean checkIdCardUnique(WuserExt wuserExt) {
        WuserExt info = wuserExtMapper.checkIdCardUnique(wuserExt.getUserIdcode());
        if (StringUtils.isNotNull(info) && info.getUserId().longValue() != wuserExt.getUserId().longValue())
        {
            return UserConstants.NOT_UNIQUE;
        }
        return UserConstants.UNIQUE;
    }

}
